home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Games / Saga / source / animtools.c < prev    next >
C/C++ Source or Header  |  2002-10-27  |  15KB  |  371 lines

  1. /* animtools.c
  2. **
  3. ** This file is a collection of tools which are used with the VSprite, Bob and Animation
  4. ** system software. It is intended as a useful EXAMPLE, and while it shows what must be
  5. ** done, it is not the only way to do it.  If Not Enough Memory, or error return, each
  6. ** cleans up after itself before returning.  NOTE that these routines assume a very specific
  7. ** structure to the GEL lists.  Make sure that you use the correct pairs together
  8. ** (i.e. makeOb()/freeOb(), etc.)
  9. **
  10. ** Compile with SAS/C 5.10b: lc -b1 -cfist -v -y -oanimtools.o animtools.c
  11. */
  12. #include <exec/types.h>
  13. #include <exec/memory.h>
  14. #include <graphics/gfx.h>
  15. #include <graphics/gels.h>
  16. #include <graphics/clip.h>
  17. #include <graphics/rastport.h>
  18. #include <graphics/view.h>
  19. #include <graphics/gfxbase.h>
  20. #include "animtools.h"
  21.  
  22.  
  23. /* Setup the GELs system.  After this call is made you can use VSprites, Bobs, AnimComps
  24. ** and AnimObs.  Note that this links the GelsInfo structure into the RastPort, and calls
  25. ** InitGels().  It uses information in your RastPort structure to establish boundary collision
  26. ** defaults at the outer edges of the raster.  This routine sets up for everything - collision
  27. ** detection and all. You must already have run LoadView before ReadyGelSys is called.
  28. */
  29. struct GelsInfo *setupGelSys(struct RastPort *rPort, BYTE reserved)
  30. {
  31. struct GelsInfo *gInfo;
  32. struct VSprite  *vsHead;
  33. struct VSprite  *vsTail;
  34.  
  35. if (NULL != (gInfo = (struct GelsInfo *)AllocMem(sizeof(struct GelsInfo), MEMF_CLEAR)))
  36.         {
  37.         if (NULL != (gInfo->nextLine = (WORD *)AllocMem(sizeof(WORD) * 8, MEMF_CLEAR)))
  38.             {
  39.             if (NULL != (gInfo->lastColor = (WORD **)AllocMem(sizeof(LONG) * 8, MEMF_CLEAR)))
  40.                 {
  41.                 if (NULL != (gInfo->collHandler = (struct collTable *)
  42.                         AllocMem(sizeof(struct collTable),MEMF_CLEAR)))
  43.                     {
  44.                     if (NULL != (vsHead = (struct VSprite *)
  45.                             AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))
  46.                         {
  47.                         if (NULL != (vsTail = (struct VSprite *)
  48.                                 AllocMem(sizeof(struct VSprite), MEMF_CLEAR)))
  49.                             {
  50.                             gInfo->sprRsrvd   = reserved;
  51.                             /* Set left- and top-most to 1 to better keep items */
  52.                             /* inside the display boundaries.                   */
  53.                             gInfo->leftmost   = gInfo->topmost    = 1;
  54.                             gInfo->rightmost  = (rPort->BitMap->BytesPerRow << 3) - 1;
  55.                             gInfo->bottommost = rPort->BitMap->Rows - 1;
  56.                             rPort->GelsInfo = gInfo;
  57.                             InitGels(vsHead, vsTail, gInfo);
  58.                             return(gInfo);
  59.                             }
  60.                         FreeMem(vsHead, (LONG)sizeof(*vsHead));
  61.                         }
  62.                     FreeMem(gInfo->collHandler, (LONG)sizeof(struct collTable));
  63.                     }
  64.                 FreeMem(gInfo->lastColor, (LONG)sizeof(LONG) * 8);
  65.                 }
  66.             FreeMem(gInfo->nextLine, (LONG)sizeof(WORD) * 8);
  67.             }
  68.         FreeMem(gInfo, (LONG)sizeof(*gInfo));
  69.         }
  70. return(NULL);
  71. }
  72.  
  73.  
  74. /* Free all of the stuff allocated by setupGelSys().  Only call this routine if
  75. ** setupGelSys() returned successfully.  The GelsInfo structure is the one returned
  76. ** by setupGelSys().   It also unlinks the GelsInfo from the RastPort.
  77. */
  78. VOID cleanupGelSys(struct GelsInfo *gInfo, struct RastPort *rPort)
  79. {
  80. rPort->GelsInfo = NULL;
  81. FreeMem(gInfo->collHandler, (LONG)sizeof(struct collTable));
  82. FreeMem(gInfo->lastColor, (LONG)sizeof(LONG) * 8);
  83. FreeMem(gInfo->nextLine, (LONG)sizeof(WORD) * 8);
  84. FreeMem(gInfo->gelHead, (LONG)sizeof(struct VSprite));
  85. FreeMem(gInfo->gelTail, (LONG)sizeof(struct VSprite));
  86. FreeMem(gInfo, (LONG)sizeof(*gInfo));
  87. }
  88.  
  89.  
  90. /* Create a VSprite from the information given in nVSprite.  Use freeVSprite()
  91. ** to free this GEL.
  92. */
  93. struct VSprite *makeVSprite(NEWVSPRITE *nVSprite)
  94. {
  95. struct VSprite *vsprite;
  96. LONG            line_size;
  97. LONG            plane_size;
  98.  
  99. line_size = sizeof(WORD) * nVSprite->nvs_WordWidth;
  100. plane_size = line_size * nVSprite->nvs_LineHeight;
  101.  
  102. if (NULL != (vsprite = (struct VSprite *)AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))
  103.         {
  104.         if (NULL != (vsprite->BorderLine = (WORD *)AllocMem(line_size, MEMF_CHIP)))
  105.             {
  106.             if (NULL != (vsprite->CollMask = (WORD *)AllocMem(plane_size, MEMF_CHIP)))
  107.                 {
  108.                 vsprite->Y          = nVSprite->nvs_Y;
  109.                 vsprite->X          = nVSprite->nvs_X;
  110.                 vsprite->Flags      = nVSprite->nvs_Flags;
  111.                 vsprite->Width      = nVSprite->nvs_WordWidth;
  112.                 vsprite->Depth      = nVSprite->nvs_ImageDepth;
  113.                 vsprite->Height     = nVSprite->nvs_LineHeight;
  114.                 vsprite->MeMask     = nVSprite->nvs_MeMask;
  115.                 vsprite->HitMask    = nVSprite->nvs_HitMask;
  116.                 vsprite->ImageData  = nVSprite->nvs_Image;
  117.                 vsprite->SprColors  = nVSprite->nvs_ColorSet;
  118.                 vsprite->PlanePick  = vsprite->PlaneOnOff = 0x00;
  119.                 InitMasks(vsprite);
  120.                 return(vsprite);
  121.                 }
  122.             FreeMem(vsprite->BorderLine, line_size);
  123.             }
  124.         FreeMem(vsprite, (LONG)sizeof(*vsprite));
  125.         }
  126. return(NULL);
  127. }
  128.  
  129.  
  130. /* Create a Bob from the information given in nBob.  Use freeBob() to free this GEL.
  131. ** A VSprite is created for this bob.  This routine properly allocates all double
  132. ** buffered information if it is required.
  133. */
  134. struct Bob *makeBob(NEWBOB *nBob)
  135. {
  136. struct Bob         *bob;
  137. struct VSprite     *vsprite;
  138. NEWVSPRITE          nVSprite ;
  139. LONG                rassize;
  140.  
  141. rassize = (LONG)sizeof(UWORD) * nBob->nb_WordWidth * nBob->nb_LineHeight * nBob->nb_RasDepth;
  142.  
  143. if (NULL != (bob = (struct Bob *)AllocMem((LONG)sizeof(struct Bob), MEMF_CLEAR)))
  144.         {
  145.         if (NULL != (bob->SaveBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))
  146.             {
  147.             nVSprite.nvs_WordWidth  = nBob->nb_WordWidth;
  148.             nVSprite.nvs_LineHeight = nBob->nb_LineHeight;
  149.             nVSprite.nvs_ImageDepth = nBob->nb_ImageDepth;
  150.             nVSprite.nvs_Image      = nBob->nb_Image;
  151.             nVSprite.nvs_X          = nBob->nb_X;
  152.             nVSprite.nvs_Y          = nBob->nb_Y;
  153.             nVSprite.nvs_ColorSet   = NULL;
  154.             nVSprite.nvs_Flags      = nBob->nb_BFlags;
  155.             /* Push the values into the NEWVSPRITE structure for use in makeVSprite(). */
  156.             nVSprite.nvs_MeMask     = nBob->nb_MeMask;
  157.             nVSprite.nvs_HitMask    = nBob->nb_HitMask;
  158.  
  159.             if ((vsprite = makeVSprite(&nVSprite)) != NULL)
  160.                 {
  161.                 vsprite->PlanePick = nBob->nb_PlanePick;
  162.                 vsprite->PlaneOnOff = nBob->nb_PlaneOnOff;
  163.                 vsprite->VSBob   = bob;
  164.                 bob->BobVSprite  = vsprite;
  165.                 bob->ImageShadow = vsprite->CollMask;
  166.                 bob->Flags       = 0;
  167.                 bob->Before      = NULL;
  168.                 bob->After       = NULL;
  169.                 bob->BobComp     = NULL;
  170.  
  171.                 if (nBob->nb_DBuf)
  172.                     {
  173.                     if (NULL != (bob->DBuffer = (struct DBufPacket *)
  174.                             AllocMem((LONG)sizeof(struct DBufPacket), MEMF_CLEAR)))
  175.                         {
  176.                         if (NULL != (bob->DBuffer->BufBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))
  177.                             return(bob);
  178.                         FreeMem(bob->DBuffer, (LONG)sizeof(struct DBufPacket));
  179.                         }
  180.                     }
  181.                 else
  182.                     {
  183.                     bob->DBuffer = NULL;
  184.                     return(bob);
  185.                     }
  186.                 freeVSprite(vsprite);
  187.                 }
  188.             FreeMem(bob->SaveBuffer, rassize);
  189.             }
  190.         FreeMem(bob, (LONG)sizeof(*bob));
  191.         }
  192. return(NULL);
  193. }
  194.  
  195.  
  196. /*
  197. ** Create a Animation Component from the information given in nAnimComp and nBob.  Use
  198. ** freeComp() to free this GEL.  makeComp() calls makeBob(), and links the Bob into an AnimComp.
  199. */
  200. struct AnimComp *makeComp(NEWBOB *nBob, NEWANIMCOMP *nAnimComp)
  201. {
  202. struct Bob      *compBob;
  203. struct AnimComp *aComp;
  204.  
  205. if ((aComp = AllocMem((LONG)sizeof(struct AnimComp),MEMF_CLEAR)) != NULL)
  206.         {
  207.         if ((compBob = makeBob(nBob)) != NULL)
  208.             {
  209.             compBob->After   = compBob->Before  = NULL;
  210.             compBob->BobComp = aComp;   /* Link 'em up. */
  211.             aComp->AnimBob      = compBob;
  212.             aComp->TimeSet      = nAnimComp->nac_Time; /* Num ticks active. */
  213.             aComp->YTrans       = nAnimComp->nac_Yt; /* Offset rel to HeadOb */
  214.             aComp->XTrans       = nAnimComp->nac_Xt;
  215.             aComp->AnimCRoutine = nAnimComp->nac_Routine;
  216.             aComp->Flags        = nAnimComp->nac_CFlags;
  217.             aComp->Timer        = 0;
  218.             aComp->NextSeq      = aComp->PrevSeq  = NULL;
  219.             aComp->NextComp     = aComp->PrevComp = NULL;
  220.             aComp->HeadOb       = NULL;
  221.             return(aComp);
  222.             }
  223.         FreeMem(aComp, (LONG)sizeof(struct AnimComp));
  224.         }
  225. return(NULL);
  226. }
  227.  
  228.  
  229. /* Create an Animation Sequence from the information given in nAnimSeq and nBob.  Use
  230. ** freeSeq() to free this GEL.  This routine creates a linked list of animation components
  231. ** which make up the animation sequence.  It links them all up, making a circular list of
  232. ** the PrevSeq and NextSeq pointers. That is to say, the first component of the sequences'
  233. ** PrevSeq points to the last component; the last component of * the sequences' NextSeq
  234. ** points back to the first component.  If dbuf is on, the underlying Bobs will be set up
  235. ** for double buffering.  If singleImage is non-zero, the pImages pointer is assumed to
  236. ** point to an array of only one image, instead of an array of 'count' images, and all
  237. ** Bobs will use the same image.
  238. */
  239. struct AnimComp *makeSeq(NEWBOB *nBob, NEWANIMSEQ *nAnimSeq)
  240. {
  241. int seq;
  242. struct AnimComp *firstCompInSeq = NULL;
  243. struct AnimComp *seqComp = NULL;
  244. struct AnimComp *lastCompMade = NULL;
  245. LONG image_size;
  246. NEWANIMCOMP nAnimComp;
  247.  
  248. /* get the initial image.  this is the only image that is used
  249. ** if nAnimSeq->nas_SingleImage is non-zero.
  250. */
  251. nBob->nb_Image = nAnimSeq->nas_Images;
  252. image_size = nBob->nb_LineHeight * nBob->nb_ImageDepth * nBob->nb_WordWidth;
  253.  
  254. /* for each comp in the sequence */
  255. for (seq = 0; seq < nAnimSeq->nas_Count; seq++)
  256.         {
  257.         nAnimComp.nac_Xt        = *(nAnimSeq->nas_Xt + seq);
  258.         nAnimComp.nac_Yt        = *(nAnimSeq->nas_Yt + seq);
  259.         nAnimComp.nac_Time      = *(nAnimSeq->nas_Times + seq);
  260.         nAnimComp.nac_Routine   = nAnimSeq->nas_Routines[seq];
  261.         nAnimComp.nac_CFlags    = nAnimSeq->nas_CFlags;
  262.         if ((seqComp = makeComp(nBob, &nAnimComp)) == NULL)
  263.             {
  264.             if (firstCompInSeq != NULL)
  265.                 freeSeq(firstCompInSeq, (LONG)nBob->nb_RasDepth);
  266.             return(NULL);
  267.             }
  268.         seqComp->HeadOb = nAnimSeq->nas_HeadOb;
  269.         /* Make a note of where the first component is. */
  270.         if (firstCompInSeq == NULL) firstCompInSeq = seqComp;
  271.         /* link the component into the list */
  272.         if (lastCompMade != NULL) lastCompMade->NextSeq = seqComp;
  273.         seqComp->NextSeq = NULL;
  274.         seqComp->PrevSeq = lastCompMade;
  275.         lastCompMade = seqComp;
  276.         /* If nAnimSeq->nas_SingleImage is zero, the image array has nAnimSeq->nas_Count images. */
  277.         if (!nAnimSeq->nas_SingleImage)
  278.             nBob->nb_Image += image_size;
  279.         }
  280. /* On The last component in the sequence, set Next/Prev to make */
  281. /* the linked list a loop of components.                        */
  282. lastCompMade->NextSeq = firstCompInSeq;
  283. firstCompInSeq->PrevSeq = lastCompMade;
  284.  
  285. return(firstCompInSeq);
  286. }
  287.  
  288.  
  289. /* Free the data created by makeVSprite().  Assumes images deallocated elsewhere. */
  290. VOID freeVSprite(struct VSprite *vsprite)
  291. {
  292. LONG    line_size;
  293. LONG    plane_size;
  294.  
  295. line_size = (LONG)sizeof(WORD) * vsprite->Width;
  296. plane_size = line_size * vsprite->Height;
  297. FreeMem(vsprite->BorderLine, line_size);
  298. FreeMem(vsprite->CollMask, plane_size);
  299. FreeMem(vsprite, (LONG)sizeof(*vsprite));
  300. }
  301.  
  302.  
  303. /* Free the data created by makeBob().  It's important that rasdepth match the depth you */
  304. /* passed to makeBob() when this gel was made. Assumes images deallocated elsewhere.     */
  305. VOID freeBob(struct Bob *bob, LONG rasdepth)
  306. {
  307. LONG    rassize =  sizeof(UWORD) * bob->BobVSprite->Width * bob->BobVSprite->Height * rasdepth;
  308.  
  309. if (bob->DBuffer != NULL)
  310.         {
  311.         FreeMem(bob->DBuffer->BufBuffer, rassize);
  312.         FreeMem(bob->DBuffer, (LONG)sizeof(struct DBufPacket));
  313.         }
  314. FreeMem(bob->SaveBuffer, rassize);
  315. freeVSprite(bob->BobVSprite);
  316. FreeMem(bob, (LONG)sizeof(*bob));
  317. }
  318.  
  319.  
  320. /* Free the data created by makeComp().  It's important that rasdepth match the depth you */
  321. /* passed to makeComp() when this GEL was made. Assumes images deallocated elsewhere.    */
  322. VOID freeComp(struct AnimComp *myComp, LONG rasdepth)
  323. {
  324. freeBob(myComp->AnimBob, rasdepth);
  325. FreeMem(myComp, (LONG)sizeof(struct AnimComp));
  326. }
  327.  
  328.  
  329. /* Free the data created by makeSeq().  Complimentary to makeSeq(), this routine goes through
  330. ** the NextSeq pointers and frees the Components.  This routine only goes forward through the
  331. ** list, and so it must be passed the first component in the sequence, or the sequence must
  332. ** be circular (which is guaranteed if you use makeSeq()).  It's important that rasdepth match
  333. ** the depth you passed to makeSeq() when this gel was made.   Assumes images deallocated elsewhere!
  334. */
  335. VOID freeSeq(struct AnimComp *headComp, LONG rasdepth)
  336. {
  337. struct AnimComp *curComp;
  338. struct AnimComp *nextComp;
  339.  
  340. /* Break the NextSeq loop, so we get a NULL at the end of the list. */
  341. headComp->PrevSeq->NextSeq = NULL;
  342.  
  343. curComp = headComp;         /* get the start of the list */
  344. while (curComp != NULL)
  345.         {
  346.         nextComp = curComp->NextSeq;
  347.         freeComp(curComp, rasdepth);
  348.         curComp = nextComp;
  349.         }
  350. }
  351.  
  352.  
  353. /* Free an animation object (list of sequences).  freeOb() goes through the NextComp
  354. ** pointers, starting at the AnimObs' HeadComp, and frees every sequence.  It only
  355. ** goes forward. It then frees the Object itself.  Assumes images deallocated elsewhere!
  356. */
  357. VOID freeOb(struct AnimOb *headOb, LONG rasdepth)
  358. {
  359. struct AnimComp *curSeq;
  360. struct AnimComp *nextSeq;
  361.  
  362. curSeq = headOb->HeadComp;          /* get the start of the list */
  363. while (curSeq != NULL)
  364.         {
  365.         nextSeq = curSeq->NextComp;
  366.         freeSeq(curSeq, rasdepth);
  367.         curSeq = nextSeq;
  368.         }
  369. FreeMem(headOb, sizeof(struct AnimOb));
  370. }
  371.